package com.bigknow.appstore.web.base.service.impl;

import com.bigknow.appstore.web.base.controller.DictController;
import com.bigknow.appstore.web.base.controller.UserController;
import com.bigknow.appstore.web.base.dao.IAuditLogDao;
import com.bigknow.appstore.web.base.service.IAuditLogService;
import com.bigknow.appstore.web.framework.util.AuthenticateUserUtil;
import com.bigknow.appstore.web.base.controller.PermissionController;
import com.bigknow.appstore.web.base.controller.RoleController;
import com.bigknow.appstore.web.base.entity.AuditLog;
import com.bigknow.appstore.web.base.entity.User;

import com.bigknow.appstore.web.framework.entity.IEntity;
import com.bigknow.appstore.web.framework.service.BaseCRUDService;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;

import java.lang.reflect.InvocationTargetException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class AuditLogService extends BaseCRUDService<AuditLog, IAuditLogDao> implements IAuditLogService {

    private Map<String, String> names = new HashMap();

    @PostConstruct
    public void init() {
        // Base
        names.put(DictController.class.getSimpleName(), "字典");
        names.put(PermissionController.class.getSimpleName(), "权限");
        names.put(RoleController.class.getSimpleName(), "角色");
        names.put(UserController.class.getSimpleName(), "用户");
    }

    @Override
    public void addByEntity(IEntity entity, Class operationClass, AuditLog.OperationType operationType) {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();

        StringBuilder sb = new StringBuilder(operationType.getDisplayName()).append(".");
        if (names.containsKey(operationClass.getSimpleName())) {
            sb.append(names.get(operationClass.getSimpleName()));
        }

        java.lang.reflect.Method method = null;
        String name = "";
        try {
            method = entity.getClass().getMethod("getName");
            Object o = method.invoke(entity);
            if (o != null) {
                name = o.toString();
            } else {
                method = entity.getClass().getMethod("getSummary");
                o = method.invoke(entity);
                if (o != null) {
                    name = o.toString();
                }
            }
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

        if (name != null && !name.trim().equals("")) {
            sb.append("记录名称[").append(name).append("].");
        }

        doAdd(entity.getId(), sb.toString(), operationClass, operationType, request.getRemoteHost());
    }

    @Override
    public List<AuditLog> findByDateRange(String start, String end) {
        return this.dao.findByDateRange(start,end);
    }

    @Override
    public void add(String id, String name, String operationContentPart, Class operationClass, AuditLog.OperationType operationType) {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        StringBuilder sb = new StringBuilder(operationType.getDisplayName()).append(operationContentPart).append(".");
        if (!org.apache.commons.lang3.StringUtils.isEmpty(name)) {
            sb.append("记录名称[").append(name).append("].");
        }
        doAdd(id, sb.toString(), operationClass, operationType, request.getRemoteHost());
    }

    private void doAdd(String id, String operationContent, Class operationClass, AuditLog.OperationType operationType, String host) {
        User user = AuthenticateUserUtil.getUser();
        AuditLog log = new AuditLog();

        if (user != null) log.setOperatorAccount(user.getAccount());
        if (id != null || !id.trim().equals("")) log.setOperationEntityId(id);

        log.setOperationEntityName(getEntityName(operationClass.getSimpleName()));
        log.setOperationClass(operationClass.toString());
        log.setOperationType(operationType);
        log.setOperationContent(operationContent);
        log.setOperationTime(new Date());
        log.setOperatorHost(host);

        save(log);
    }


    private String getEntityName(String className) {
        if (className.contains("Controller")) {
            return className.replace("Controller", "");
        } else {
            return className;
        }
    }
}
